import $ from "jquery";
import { uniqueID } from "./utils";
const uniqueId = uniqueID(5);

/**
 *
 * new Popover(
 *  button1,
 *   {
 *     placement: "top-right",
 *   },
 *   "这是一个问题"
 *);
 */

// 当Popover添加一个button之后,会为button元素添加一个事件,当鼠标移入button元素上时,会向body中添加popover元素,并将popover元素定位到button元素的下方,当鼠标移出button元素上时,0.5秒后会移除popover元素
export class Popover {
  constructor($button, options, content = null) {
    this.options = {
      placement: "top-left",
      autoHide: true,
      ...options,
    };
    this.$button = $button;
    this.content = content;
    this.addButtonEvent(this.$button);
    this.id = `popover-${uniqueId()}`;
  }

  static render(id, content, options = {}) {
    return `<div class="pfui-popover" data-popover-id="${id}">
      <div class="pfui-popover-content">
        ${content || "什么都没有说"}
      </div>
      <div class="triangle ${options.placement}"></div>
    </div>`;
  }
  $button;
  $dom;
  id;
  options;
  content;
  hideTimeout;
  addContent(cb) {
    this.$dom.find(".pfui-popover-content").html(cb(this));
  }
  show(placement = "top-left") {
    // 渲染出的dom插入到body,并将dom定位到button元素的上方,注意不能超过window的边界

    let top_or_bottom_gap = 20;
    let { top, isTransform } = this.calcTop(placement, top_or_bottom_gap);
    let { left, _isTransform } = this.calcLeft(placement.split("-")[1]);
    this.$dom.css({
      top,
      left,
      opacity: 1,
    });

    this.calcTriangleToCenter(placement, isTransform);
    this.transformTriangle(placement, isTransform, _isTransform);
  }
  calcTop(placementFirst, gap) {
    let top,
      isTransform = false;
    let up = this.$button.offset().top - this.$dom.outerHeight() - gap;
    let down = this.$button.offset().top + this.$button.outerHeight() + gap;
    let center =
      this.$button.offset().top +
      this.$button.outerHeight() / 2 -
      this.$dom.outerHeight() / 2;
    if (placementFirst.includes("top")) {
      top = up;
    } else if (placementFirst.includes("bottom")) {
      top = down;
    } else {
      top = center;
    }
    if (top < 0) {
      top = down;
      isTransform = true;
    } else if (top + this.$dom.outerHeight() > $(window).height()) {
      top = up;
      isTransform = true;
    }
    return { top, isTransform };
  }
  calcLeft(placementSecond) {
    let _left,
      isTransform = false;
    let left =
      this.$button.offset().left -
      this.$dom.outerWidth() +
      this.$button.height();
    let right =
      this.$button.offset().left +
      this.$button.outerWidth() -
      this.$button.height();
    let center =
      this.$button.offset().left +
      this.$button.outerWidth() / 2 -
      this.$dom.outerWidth() / 2;
    if (placementSecond === "left") {
      _left = left;
    } else if (placementSecond === "right") {
      _left = right;
    } else {
      _left = center;
    }
    if (left < 0) {
      _left = 0;
      isTransform = true;
    } else if (_left + this.$dom.outerWidth() > $(window).width()) {
      _left = 0;
      isTransform = true;
    }
    return { left: _left, isTransform };
  }
  calcTriangleToCenter(placement) {
    let $triangle = this.$dom.find(".triangle");
    // 只有placement带有top或者bottom时,才需要调整triangle的位置,此时triangle永远指向button元素的下方或者上方,只需要移动triangle的左右位置即可
    if (placement.includes("top") || placement.includes("bottom")) {
      let btn_left = this.$button.offset().left;
      let dom_left = this.$dom.offset().left;
      let triangle_left =
        btn_left - dom_left + this.$button.outerWidth() / 2 - 10;
      $triangle.css({
        left: triangle_left,
      });
    }
  }
  transformTriangle(placement, transformTop, transformLeft) {
    let $triangle = this.$dom.find(".triangle");
    let transform_class = placement;
    if (transformTop) {
      if (placement.includes("top")) {
        transform_class = placement.replace("top", "bottom");
      } else if (placement.includes("bottom")) {
        transform_class = placement.replace("bottom", "top");
      }
    }
    if (transformLeft) {
      if (placement.includes("left")) {
        transform_class = placement.replace("left", "right");
      } else if (placement.includes("right")) {
        transform_class = placement.replace("right", "left");
      }
    }

    $triangle.removeClass().addClass(["triangle", transform_class]);
  }
  hidden() {
    // 500毫秒后隐藏popover元素

    this.hideTimeout = setTimeout(() => {
      this.$dom.animate(
        {
          opacity: 0,
        },
        100,
        () => {
          this.$dom.remove();
        }
      );
    }, 300);
  }
  render(id) {
    // 会调用Popover.render方法,渲染出popover元素,并插入到document中
    if (!this.$dom) {
      $("body").append(Popover.render(id, this.content, this.options));
      this.$dom = $(`[data-popover-id="${id}"]`);
    } else {
      $("body").append(this.$dom);
    }

    return this.$dom;
  }
  addButtonEvent($button) {
    // 鼠标移入button元素上时,会向body中添加popover元素,当鼠标移出button元素上时,会移除popover元素

    $button.on("mouseenter", () => {
      this.render(this.id);
      this.addPopoverEvent(this.$dom);
      this.show(this.options.placement);
    });
    $button.on("mouseleave", () => {
      if (this.options.autoHide) this.hidden();
    });
  }
  addPopoverEvent($dom) {
    $dom.on("mouseenter", () => {
      console.log("$dom mouseenter");
      clearTimeout(this.hideTimeout);
    });
    $dom.on("mouseleave", () => {
      console.log("$dom mouseleave");
      if (this.options.autoHide) this.hidden();
    });
  }
}
